<template>
  <div class="tween-gift" :style="boxStyles">
    {{ value.username }}
    <img :src="value.src" alt="" class="gift-image">
    <span v-if="amount" class="gift-amount" :style="amountStyles">x {{ amount }}</span>
  </div>
</template>

<script>
import TWEEN from '@tweenjs/tween.js'
export default {
  props: {
    value: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data () {
    return {
      amount: 0,
      left: -100,
      scale: 1,
      amountTween: null, // 礼物数量tween
      stayTime: 2000, // 礼物动画完，停留时间
      frameHandler: null, // 动画具柄
      timer: null,
      repeat: 0
    }
  },
  computed: {
    boxStyles () {
      return {
        transform: `translateX(${this.left}%)`
      }
    },
    amountStyles () {
      return {
        transform: `translateX(100%) scale(${this.scale})`
      }
    }
  },
  watch: {
    'value.amount' (value) {
      this.repeat = value
      this.animateAmount()
    }
  },
  mounted () {
    this.repeat = this.value.amount
    this.animateHandler()
  },
  methods: {
    animateAmount () {
      this.scale = 5
      clearInterval(this.timer) // 清除定时器
      if (this.amountTween) {
        this.amountTween.stop().repeat(this.repeat - this.amount).start()
        return
      }
      this.amountTween = new TWEEN.Tween(this.$data)
        .easing(TWEEN.Easing.Cubic.Out)
        .to({ scale: 1 }, 350)
        .repeat(this.repeat - this.amount)
        .onRepeat(() => {
          this.amount += 1
        })
        .onComplete(() => {
          this.amount = this.repeat // 确保最终结果正确
          this.timer = setTimeout(() => {
            this.$emit('complete', this.value)
            cancelAnimationFrame(this.frameHandlerd)
          }, this.stayTime)
        })
        .start()
    },
    animateHandler (newValue) {
      const animate = (time) => {
        this.frameHandler = requestAnimationFrame(animate)
        TWEEN.update(time)
      }
      new TWEEN.Tween(this.$data)
        .easing(TWEEN.Easing.Cubic.Out)
        .to({ left: 0 }, 300)
        .onComplete(() => this.animateAmount(newValue))
        .start()
      animate()
    }
  }
}
</script>

<style lang="scss">
.tween-gift {
  color: #666;
  padding: 10px 20px;
  white-space: nowrap;
  background: #fff;
  border-top-right-radius: 1000px;
  border-bottom-right-radius: 1000px;
}
.gift-amount {
  position: absolute;
  right: -10px;
  transform-origin: left center;
}
.gift-image {
  display: inline-block;
  height: 30px;
  width: 30px;
  vertical-align: middle;
  margin-left:15px;
}
</style>
